package user

import (
	"context"
	"fmt"

	"golang.org/x/crypto/bcrypt"
)

const Appname = "user"

// 定义实现接口的结构体
type UserService interface {
	CreateUser(context.Context, *CreateUserRequest) (*User, error)
	DescribeUser(context.Context, *DescribeUserRequest) (*User, error)
	DeleteUser(context.Context, *DeleteUserRequest) error
}

type CreateUserRequest struct {
	Username string `json:"username"`
	Password string `json:"password"`
	// 后面的中间件鉴权时，会用到Role
	Role Role `json:"role"`
	// Dep:部门A。Label 字段是一个 map[string]string 类型的字段，它被用来存储非结构化的数据，无法直接存入到关系型数据库中，所以要序列化json格式，在存入数据库中
	Label map[string]string `json:"label" gorm:"serializer:json"`
	// 用来判断密码是否加密
	isHashed bool
}

func NewCreateUserRequest() *CreateUserRequest {
	return &CreateUserRequest{
		Label: map[string]string{},
	}
}

// 扩展CreateUserRequest的方法，实现校验逻辑
func (req *CreateUserRequest) Validate() error {
	if req.Username == "" || req.Password == "" {
		return fmt.Errorf("请输入用户名或密码")
	}
	return nil
}

// 扩展CreateUserRequest的方法，实现密码加密
func (req *CreateUserRequest) PasswordHash() {
	if req.isHashed {
		return
	}
	b, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		panic(err)
	}
	req.Password = string(b)
	req.isHashed = true
}

type DescribeUserRequest struct {
	DescribeBy    DescribeBy
	DescribeValue string
}

// 用id来构造DescribeUserRequest实例
func NewDescribeByID(id string) *DescribeUserRequest {
	return &DescribeUserRequest{
		// 没写DescribeBy就默认表示为0
		DescribeValue: id,
	}
}

// 用username来构造DescribeUserRequest实例
func NewDescribeByUsername(username string) *DescribeUserRequest {
	return &DescribeUserRequest{
		DescribeBy:    1,
		DescribeValue: username,
	}
}

type DeleteUserRequest struct {
	ID string
}

func NewDeleteUserRequest(id string) *DeleteUserRequest {
	return &DeleteUserRequest{
		ID: id,
	}
}
